package config

import (
	"flag"
	"github.com/spf13/viper"
	"log"
	"os"
	"strings"
)

var (
	v   *viper.Viper
	Cfg Config
)

func init() {

	v = viper.New()

	//读取环境变量值
	v.SetEnvPrefix("APP")
	v.AutomaticEnv()
	replacer := strings.NewReplacer(".", "_")
	v.SetEnvKeyReplacer(replacer)

	// 共同配置
	v.SetDefault("db_url", "root:123@tcp(example.com:3306)?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai") //时间戳
	v.SetDefault("http_port", 80)
	v.SetDefault("log_level", "info")
	v.SetDefault("log_file", "log.txt")
	v.SetDefault("gin_mode", "debug")

	err := v.Unmarshal(&Cfg)
	if err != nil {
		log.Println(err)
		return
	}

	// 默认位置
	if err := LoadConfigByFile("config.toml"); err != nil {
		log.Println(err.Error())
		return
	}

	// 默认位置
	if err := LoadConfigByFile("D:\\Users\\Administrator\\IdeaProjects\\elflog\\config.toml"); err != nil {
		log.Println(err.Error())
		return
	}

	// 没有环境变量
	configFile := os.Getenv("APP_LOG_CONFIG_PATH")
	if configFile != "" {
		// 加载配置文件
		log.Println("set config file from env APP_CONFIG_PATH " + configFile)
		if err := LoadConfigByFile(configFile); err != nil {
			log.Println(err.Error())
			return
		}
	}

	// 命令行配置文件优先级最高
	TryLoadFromArgConfigFile()
}

func TryLoadFromArgConfigFile() bool {
	// The default set of command-line flags, parsed from os.Args.
	file, _ := os.Open("/dev/null")
	var commandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
	commandLine.SetOutput(file)
	var configFilePath = commandLine.String("config", "", "配置文件")
	err := commandLine.Parse(os.Args[1:])
	if err != nil {
		log.Printf("没有config %v", err)
	}
	if *configFilePath != "" {
		_ = LoadConfigByFile(*configFilePath)
		return true
	}
	return false
}

func LoadConfigByFile(name string) error {
	v.SetConfigFile(name)
	if err := v.ReadInConfig(); err != nil {
		switch err.(type) {
		case viper.ConfigFileNotFoundError:
			//err = Conf.v.WriteConfigAs("config.yaml") //new config file and ignore err
			log.Println("no config file use default:", err)
		default:
			log.Println(err)
		}
	}
	err := v.Unmarshal(&Cfg)
	if err != nil {
		return err
	}
	return nil
}
